#include<sys/types.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>

#define eeprom_size 1024

void show_usage(char *exe_name)
{
    printf("使用说明:\n");
    printf("该程序用于测试用户eeprom读写\n");
    printf("用户可用eeprom最大容量:  %d (字节)\n", eeprom_size);
	printf("请输入正确的测试参数:\n");
	printf("写入测试: %s -w 位置(范围:0~%d) 内容(字符个数:1~%d)\n",exe_name, eeprom_size-1, eeprom_size);
	printf("读出测试: %s -r 位置(范围:0~%d) 长度(取值范围:1~%d)\n",exe_name, eeprom_size-1, eeprom_size);
	printf("擦除测试: %s -e 用0xff填充整个eeprom的%d字节\n", exe_name, eeprom_size);
	printf("读写测试: %s -t 快速测试设备读写功能\n", exe_name);
}

int main(int argc, char **argv)
{
    int ret = 0;

	/*读写长度*/
    int len = 0;

	/*读写位置*/
	int pos = 0;

	/*文件句柄*/
    int eepromfd  = -1;

    char rwbuf[eeprom_size] = {'\0'};
    char rdbuf[eeprom_size] = {'\0'};

    eepromfd = open("/ual/eeprom", O_RDWR);
    if (eepromfd < 0) 
	{
        perror("打开/ual/eeprom设备失败\n");
		goto failed_end;
    }

	/*基本参数个数判定*/
    if(argc < 2) 
	{
        show_usage(argv[0]);
        goto failed_end;
    }

    if(!strcmp(argv[1],"-w"))
	{
		/*如果写入测试*/
	   if(argc != 4) 
		{
			/*参数必须是４个*/
            show_usage(argv[0]);
			goto failed_end;
        }

		/*获得写入位置*/
		pos = atoi(argv[2]);
		if(pos < 0 || pos > (eeprom_size-1))
		{
            fprintf(stderr,"写入位置错误, 位置:%d, 范围限制: 0~%d\n", pos, eeprom_size-1);
			goto failed_end;
		}

		/*获得写入内容*/
        strcpy(rwbuf,argv[3]);

		/*获得写入长度*/
        len = strlen(rwbuf);
		if(len <= 0 || len > eeprom_size)
		{
            fprintf(stderr,"写入长度错误, 长度:%d, 范围限制: 1~%d\n", len, eeprom_size);
			goto failed_end;
		}

		/*判定写入位置与写入长度之间的逻辑关系*/
		if(len > (eeprom_size - pos))
		{
            fprintf(stderr,"设备容量不足, 长度:%d, 位置:%d, 可用容量: %d\n", len, pos, (eeprom_size-pos));
			goto failed_end;
		}

		/*设置写入位置*/
		ret = lseek(eepromfd, pos, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"设置写入位置失败, 位置:%d, 返回码: %d\n", pos, ret);
			goto failed_end;
        }

		/*执行内容写入*/
        ret = write(eepromfd, rwbuf, len);
        if(ret != len)
		{
            fprintf(stderr,"执行写入内容失败，返回码: %d\n", ret);
			goto failed_end;
        }

		/*重置写入位置*/
		ret = lseek(eepromfd, 0, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置写入位置失败: 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }
        printf("执行结果:[OK]\n");
        printf("写入位置: %d\n", pos);
        printf("写入长度: %d\n", len);
        printf("写入内容: \n%s\n", rwbuf);
    }
	else  if(!strcmp(argv[1],"-r"))
	{
		/*如果读出测试*/
	   if(argc != 4) 
		{
			/*参数必须是４个*/
            show_usage(argv[0]);
			goto failed_end;
        }

		/*获得读出位置*/
		pos = atoi(argv[2]);
		if(pos < 0 || pos > (eeprom_size-1))
		{
            fprintf(stderr,"读出位置错误, 位置:%d, 范围限制: 0~%d\n", pos, eeprom_size-1);
			goto failed_end;
		}

		/*获得读出长度*/
        len = atoi(argv[3]);
		if(len <= 0 || len > eeprom_size)
		{
            fprintf(stderr,"读出长度错误, 长度:%d, 范围限制: 1~%d\n", len, eeprom_size);
			goto failed_end;
		}

		/*判定写入位置与写入长度之间的逻辑关系*/
		if(len > (eeprom_size - pos))
		{
            fprintf(stderr,"设备容量不足, 长度:%d, 位置: %d  可用容量: %d\n", len, pos, (eeprom_size-pos));
			goto failed_end;
		}

		/*设置读出位置*/
		ret = lseek(eepromfd, pos, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"设置读出位置失败, 位置:%d, 返回码:%d\n", pos, ret);
			goto failed_end;
        }

		/*执行内容读出*/
        ret = read(eepromfd,rwbuf,len);
        if(ret != len)
		{
            fprintf(stderr,"执行读出内容失败，返回码: %d\n", ret);
			goto failed_end;
        }

		/*重置读出位置*/
		ret = lseek(eepromfd, 0, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置读出位置失败, 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }
        printf("执行结果:[OK]\n");
        printf("读出位置: %d\n", pos);
        printf("读出长度: %d\n", len);
        printf("读出内容: \n%s\n", rwbuf);
    }
	else  if(!strcmp(argv[1],"-e"))
	{
        len = eeprom_size;
		pos = 0;

		memset(rwbuf, 0xff, eeprom_size);

		/*重置写入位置*/
		ret = lseek(eepromfd, 0, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置写入位置失败, 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }

		/*执行内容写入*/
        ret = write(eepromfd, rwbuf, len);
        if(ret != len)
		{
            fprintf(stderr,"执行写入内容失败，返回码: %d\n", ret);
			goto failed_end;
        }

		/*重置写入位置*/
		ret = lseek(eepromfd, 0, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置写入位置失败: 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }
        printf("执行结果:[OK]\n");
        printf("写入位置: %d\n", pos);
        printf("写入长度: %d\n", len);
	}else if(!strcmp(argv[1],"-t"))
	{
		/*如果读写测试*/

		/*获得写入位置*/
		pos = 0;

		/*获得写入内容*/
        strcpy(rwbuf,"abcdefg");

		/*获得写入长度*/
        len = strlen(rwbuf);

		/*设置写入位置*/
		ret = lseek(eepromfd, pos, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"设置写入位置失败, 位置:%d, 返回码: %d\n", pos, ret);
			goto failed_end;
        }

		/*执行内容写入*/
        ret = write(eepromfd, rwbuf, len);
        if(ret != len)
		{
            fprintf(stderr,"执行写入内容失败，返回码: %d\n", ret);
			goto failed_end;
        }

		/*重置写入位置*/
		ret = lseek(eepromfd, pos, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置写入位置失败: 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }

		/*执行内容读出*/
        ret = read(eepromfd,rdbuf,len);
        if(ret != len)
		{
            fprintf(stderr,"执行读出内容失败，返回码: %d\n", ret);
			goto failed_end;
        }

		/*重置读出位置*/
		ret = lseek(eepromfd, 0, SEEK_SET);
		if(ret < 0)
		{
            fprintf(stderr,"重置读出位置失败, 位置:%d, 返回码: %d\n", 0, ret);
			goto failed_end;
        }
		/*比较读写内容*/
    	if(!strcmp(rwbuf, rdbuf))
		{
			printf("[OK]\n");
		}else
		{
			printf("[ERROR]\n");
		}
	}

/*正常时程序出口*/
finish_end:
	if(eepromfd != -1)
	{
		close(eepromfd);
		eepromfd = -1;
	}
    return 0;

/*错误时程序出口*/
failed_end:
	if(eepromfd != -1)
	{
		close(eepromfd);
		eepromfd = -1;
	}
	return 1;
}
